/*
	Prototype is developed by Benato Denis.
	Prototype is a project started on 23/09/2013.
	Prototype is release under LGPLv3 license.
	If you use part of Prototype software on other
	projects, you must copy this comment into the source
	code of the other projects, and quote Benato Denis 
	in the credits of the other software.
*/

#include "Prototype.h"

#include "Memory.h"

void ResetEveryByte(struct Data* bytes)
{
	while (bytes->Previous != (struct Data*)NULL)
		bytes = bytes->Previous;
	while (bytes->Next != (struct Data*)NULL)
	{
		bytes->DataOnByte = (unsigned char)0x00;
		bytes = bytes->Next;
	}
	bytes->DataOnByte = (unsigned char)0x00;
}

void DeleteEveryByte(struct Data* bytes)
{
	while (bytes->Previous != (struct Data*)NULL)
		bytes = bytes->Previous;
	while (bytes->Next != (struct Data*)NULL)
	{
		bytes = bytes->Next;
		delete bytes->Previous;
		bytes->Previous = (struct Data*)NULL;
	}
	delete bytes;
}

Memory::Memory()
{
	this->CurrentData = new struct DataSequence;
	this->CurrentData->Next = (struct DataSequence*)NULL;
	this->CurrentData->Previous = (struct DataSequence*)NULL;
	struct Data* NewByte = new struct Data;
	NewByte->Next = (struct Data*)NULL;
	NewByte->Previous = (struct Data*)NULL;
	NewByte->DataOnByte = (unsigned char)0x00;
	this->CurrentData->Byte = NewByte;
	NewByte = (struct Data*)NULL;
	this->ProgramStack = new Stack;
}

Memory::~Memory()
{
	while (this->CurrentData->Previous != (struct DataSequence*)NULL)
		this->CurrentData = this->CurrentData->Previous;
	while (this->CurrentData->Next != (struct DataSequence*)NULL)
	{
		DeleteEveryByte(this->CurrentData->Byte);
		this->CurrentData->Byte = (struct Data*)NULL;
		this->CurrentData = this->CurrentData->Next;
		delete this->CurrentData->Previous;
		this->CurrentData->Previous = (struct DataSequence*)NULL;
	}
	DeleteEveryByte(this->CurrentData->Byte);
	this->CurrentData->Byte = (struct Data*)NULL;
	delete this->CurrentData->Previous;
	this->CurrentData->Previous = (struct DataSequence*)NULL;
	delete this->ProgramStack;
}

void Memory::Reset()
{
	while (this->CurrentData->Previous != (struct DataSequence*)NULL)
		this->CurrentData = this->CurrentData->Previous;
	while (this->CurrentData->Next != (struct DataSequence*)NULL)
	{
		ResetEveryByte(this->CurrentData->Byte);
		this->CurrentData = this->CurrentData->Next;
	}
	ResetEveryByte(this->CurrentData->Byte);
	delete this->ProgramStack;
	this->ProgramStack = new Stack;
}

void Memory::GotoNextByte()
{
	if (this->CurrentData->Byte->Next == (struct Data*)NULL)
	{
		struct Data* NewByte = new struct Data;
		NewByte->Next = (struct Data*)NULL;
		NewByte->Previous = this->CurrentData->Byte;
		NewByte->DataOnByte = (unsigned char)0x00;
		this->CurrentData->Byte->Next = NewByte;
	}
	this->CurrentData->Byte = this->CurrentData->Byte->Next;
}

void Memory::GotoPreviousByte()
{
	if (this->CurrentData->Byte->Previous == (struct Data*)NULL)
	{
		struct Data* NewByte = new struct Data;
		NewByte->Next = this->CurrentData->Byte;
		NewByte->Previous = (struct Data*)NULL;
		NewByte->DataOnByte = (unsigned char)0x00;
		this->CurrentData->Byte->Previous = NewByte;
	}
	this->CurrentData->Byte = this->CurrentData->Byte->Previous;
}

void Memory::SetByte(unsigned char NewValue)
{
	this->CurrentData->Byte->DataOnByte = NewValue;
}

unsigned char Memory::GetByte()
{
	return this->CurrentData->Byte->DataOnByte;
}

void Memory::GotoNextByteList()
{
	if (this->CurrentData->Next == (struct DataSequence*)NULL)
	{
		struct DataSequence* NewByteSequence = new struct DataSequence;
		NewByteSequence->Next =(struct DataSequence*)NULL;
		NewByteSequence->Previous = this->CurrentData;
		struct Data* NewByte = new struct Data;
		NewByte->Next = (struct Data*)NULL;
		NewByte->Previous = (struct Data*)NULL;
		NewByte->DataOnByte = (unsigned char)0x00;
		NewByteSequence->Byte = NewByte;
		this->CurrentData->Next = NewByteSequence;
	}
	this->CurrentData = this->CurrentData->Next;
}


void Memory::GotoPreviousByteList()
{
	if (this->CurrentData->Previous == (struct DataSequence*)NULL)
	{
		struct DataSequence* NewByteSequence = new struct DataSequence;
		NewByteSequence->Next = this->CurrentData;
		NewByteSequence->Previous = (struct DataSequence*)NULL;
		struct Data* NewByte = new struct Data;
		NewByte->Next = (struct Data*)NULL;
		NewByte->Previous = (struct Data*)NULL;
		NewByte->DataOnByte = (unsigned char)0x00;
		NewByteSequence->Byte = NewByte;
		this->CurrentData->Previous = NewByteSequence;
	}
	this->CurrentData = this->CurrentData->Previous;
}

void Memory::POP()
{
	struct Data* CurrentByte = CurrentData->Byte;
	CurrentByte->DataOnByte = this->ProgramStack->POP();
}

void Memory::PUSH()
{
	struct Data* CurrentByte = CurrentData->Byte;
	this->ProgramStack->PUSH(CurrentByte->DataOnByte);
}